package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementsApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.domain.PageResult;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.ThreadLocalUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

//圈子
@Service
public class MovementsService {


    @DubboReference
    private MovementsApi movementsApi;

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
   private UserInfoApi userInfoApi;


    @Autowired
    private RedisTemplate<String,String> redisTemplate;



    /**
     * 发布朋友圈:
     */
    public void publishMoments(Movement movement, MultipartFile[] multipartFiles) throws IOException {

        //1.判断动态文本内容是否为空，为空则抛出一个文本异常
        if(StringUtils.isEmpty(movement.getTextContent())){
            throw new BusinessException(ErrorResult.contentError());
        }
        //2.获取当前登录用户的用户id
        Long userId = ThreadLocalUtils.getUserId();
        //3.调用阿里云组件，把动态的图片或视频上传到阿里云oss，得到访问路径;
        List<String> list = new ArrayList<>();
        for (MultipartFile multipartFile : multipartFiles) {
        //这行代码已经把图片上传至阿里云，并得到访问路径
            String imageUrl = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            list.add(imageUrl);
        }
        //4.把用户id和图片访问路径的集合封装进movenment对象
        movement.setUserId(userId);
        movement.setMedias(list);

        //5.调用api完成动态发布
        movementsApi.publishMoments(movement);
    }



    /**
     *
     * 查看我的朋友圈
     */
    public PageResult lookMyMoments(Integer page, Integer pagesize, Long userId) {
        //调用movementsApi分页查询我的动态详情
        PageResult pageResult = movementsApi.lookMYMoments(page,pagesize,userId);
        //2.获取所有的动态详情
        List<Movement> movements = (List<Movement>) pageResult.getItems();
        //3.判断 movements是否为空，为空直接返回pageResult

        if(movements == null){
            return pageResult;
        }

        //4.根据当前登录的用户id调用UserInfo查询用户详情
        UserInfo userInfo = userInfoApi.selectUserInfo(userId);

        List<MovementsVo> list = new ArrayList<>();
        //5.遍历movements
        for (Movement movement : movements) {
            MovementsVo movementsVo = MovementsVo.init(userInfo, movement);
            list.add(movementsVo);
        }

        //6.构造返回数据
        pageResult.setItems(list);

        return pageResult;


    }


    /**
     *  查看好友动态
     */
    public PageResult viewSocialUpdates(Integer page, Integer pageSize) {

        //1.获取当前登录的用户id
        Long userId = ThreadLocalUtils.getUserId();
        //2.调用api查看好友的动态详情集合
        List<Movement> movements = movementsApi.viewSocialUpdates(userId, page, pageSize);

        //3.判断movements是否为空,为空直接new一个PageResult返回,为空的意思是当前登录的用户没有好友发布动态
        if(CollUtil.isEmpty(movements)){//ddd,这个害我搞了半天，之前我用的是movements == null,害死人
                                        //走到这步movements为空的时候程序会一直往下走，不会停掉返回；
                                          //然后就会在下面掉用userInfo的时候因为movements为空报mysql的sql语法错误
            return new PageResult();
        }

        //4.先批量获取好友动态详情表中的用户id，再根据批量的用户id批量获取用户详情
        List<Long> userIds = CollUtil.getFieldValues(movements, "userId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.batchQueryUserInfo(userIds, null);//null参数位置为条件


        //5.遍历movements集合，每遍历一个动态详情表就构造一个vo对象
        List<MovementsVo> movementsVos = new ArrayList<>();

        for (Movement movement : movements) {
            Long id = movement.getUserId();
            UserInfo userInfo = userInfoMap.get(id);
            if(userInfo != null){
                MovementsVo movementsVo = MovementsVo.init(userInfo, movement);

                //修复动态点赞bug
                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();//动态id
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + ThreadLocalUtils.getUserId();

                if(redisTemplate.opsForHash().hasKey(key, hashKey)){
                    movementsVo.setHasLiked(1);
                }

                String loveHashKey = Constants.MOVEMENT_LOVE_HASHKEY  + ThreadLocalUtils.getUserId();
                if(redisTemplate.opsForHash().hasKey(key, loveHashKey)){
                    movementsVo.setHasLoved(1);
                }



                movementsVos.add(movementsVo);
            }
        }

        //6.构造返回条件
        return new PageResult(page,pageSize,0,movementsVos);
    }



    /**
     *
     * 查看大数据系统推荐的动态
     */
    public PageResult lookRecommendMoments(Integer page, Integer pageSize) {

        //1.从Redis中获取大数据推荐系统要推送的动态详情存入的动态详情pid
        //1.1先获取当前登录的用户id
        Long userId = ThreadLocalUtils.getUserId();
       String redisKey = Constants.MOVEMENTS_RECOMMEND + userId;
        String redisValue = redisTemplate.opsForValue().get(redisKey);

        //2.判断大数据推荐系统有没有推荐动态详情
        // 判断redisValue是否为空,为空则自己随机推荐几条动态详情给用户

        List<Movement> movements = Collections.EMPTY_LIST;

        if (StringUtils.isEmpty(redisValue)){
            movements = movementsApi.randomMoments(pageSize);
        }else{
            //3.大数据系统根据用户的行为特征计算出要推送给用户的动态详情
            //处理pid
            String[] pids = redisValue.split(",");

            if( (page - 1) * pageSize < pids.length) {

                //这两行没有注释，因为我自己也不怎么理解
                List<Long> longPids = Arrays.stream(pids).skip((page - 1) * pageSize).limit(pageSize)
                        .map(e -> Long.valueOf(e))
                        .collect(Collectors.toList());


                //4.调用api完成批量查询动态详情
                movements =movementsApi.lookRecommendMoments(longPids);
            }
        }


        //5.先从查询出来的要推荐给用户的动态详情集合里获取全部用户id
        //调用UserInfo查询全部用户的用户详情
        List<Long> userIds = CollUtil.getFieldValues(movements, "userId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.batchQueryUserInfo(userIds, null);

        //6.遍历查出来要推荐给用户的动态详情集合，每一个动态详情集合构建一个vo对象

        List<MovementsVo> movementsVos = new ArrayList<>();
        for (Movement movement : movements) {
            //获取用户id
            Long id = movement.getUserId();
            //根据用户id获取用户详情
            UserInfo userInfo = userInfoMap.get(id);
            if(userInfo != null){
                MovementsVo movementsVo = MovementsVo.init(userInfo, movement);

                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + ThreadLocalUtils.getUserId();

                if(redisTemplate.opsForHash().hasKey(key, hashKey)){
                    movementsVo.setHasLiked(1);
                }

                String loveHashKey = Constants.MOVEMENT_LOVE_HASHKEY  + ThreadLocalUtils.getUserId();
                if(redisTemplate.opsForHash().hasKey(key, loveHashKey)){
                    movementsVo.setHasLoved(1);
                }
                movementsVos.add(movementsVo);
            }

        }

        //7.构造返回值
        PageResult pageResult = new PageResult(page, pageSize ,0,movementsVos);
        return pageResult;

    }


    /**
     *
     * 查看单条动态
     */
    public MovementsVo lookOneMoment(String movementId) {

        //1.调用api查询动态
        Movement movement = movementsApi.lookOneMoment(movementId);

        MovementsVo movementsVo =null;

        //2.非空校验
        if (movement == null) {
            return null;
        } else {
            //调用userInfoApi查用户详情
            UserInfo userInfo = userInfoApi.selectUserInfo(movement.getUserId());
            if (userInfo != null) {

                 movementsVo = MovementsVo.init(userInfo, movement);

                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + ThreadLocalUtils.getUserId();

                if (redisTemplate.opsForHash().hasKey(key, hashKey)) {
                    movementsVo.setHasLiked(1);
                    movementsVo.setLikeCount(1);
                }

                String loveHashKey = Constants.MOVEMENT_LOVE_HASHKEY + ThreadLocalUtils.getUserId();
                if (redisTemplate.opsForHash().hasKey(key, loveHashKey)) {
                    movementsVo.setHasLoved(1);
                }



            }

        }

        return movementsVo;
    }
}
